/**
 * @copyright 2021 Xoan Iago Suarez Canosa. All rights reserved.
 * Constact: iago.suarez@thegraffter.com
 * Software developed in the PhD: Low-level vision for resource-limited devices
 */
#include <interest_point/BAD.h>
#include <cassert>
#include <vector>

#define UPM_DEGREES_TO_RADS 0.017453292519943295
#define UPM_ROUNDNUM(x) (static_cast<int>(x + 0.5f))
#define UPM_BAD_EXTRA_RATIO_MARGIN 1.75

namespace upm {
/**
 * @brief Rectifies the coordinates of the box pairs measurement functions with the keypoint
 * location parameters.
 * @param boxes_params The input parameters defining the location of each pair of boxes inside
 * the normalized (32x32) patch.
 * @param out_params The output parameters, now the boxes are located in the full image.
 * @param kp The keypoint defining the offset, rotation and scale to be applied
 * @param scale_factor A scale factor that magnifies the measurement functions w.r.t. the keypoint.
 * @param patch_size The size of the normalized patch where the measurement functions were learnt.
 */
static inline void rectifyBoxes(const std::vector<BAD::BoxPairParams> &boxes_params,
                                std::vector<BAD::BoxPairParams> &out_params,
                                const cv::KeyPoint &kp,
                                float scale_factor = 1,
                                const cv::Size &patch_size = cv::Size(32, 32)) {
  float m00, m01, m02, m10, m11, m12;
  float s, cosine, sine;

  s = scale_factor * kp.size / (0.5f * (patch_size.width + patch_size.height));
  out_params.resize(boxes_params.size());

  if (kp.angle == -1) {
    m00 = s;
    m01 = 0.0f;
    m02 = -0.5f * s * patch_size.width + kp.pt.x;
    m10 = 0.0f;
    m11 = s;
    m12 = -s * 0.5f * patch_size.height + kp.pt.y;
  } else {
    cosine = (kp.angle >= 0) ? static_cast<float>(cos(kp.angle * UPM_DEGREES_TO_RADS)) : 1.f;
    sine = (kp.angle >= 0) ? static_cast<float>(sin(kp.angle * UPM_DEGREES_TO_RADS)) : 0.f;

    m00 = s * cosine;
    m01 = -s * sine;
    m02 = (-s * cosine + s * sine) * patch_size.width * 0.5f + kp.pt.x;
    m10 = s * sine;
    m11 = s * cosine;
    m12 = (-s * sine - s * cosine) * patch_size.height * 0.5f + kp.pt.y;
  }

  for (size_t i = 0; i < boxes_params.size(); i++) {
    out_params[i].x1 = UPM_ROUNDNUM(m00 * boxes_params[i].x1 + m01 * boxes_params[i].y1 + m02);
    out_params[i].y1 = UPM_ROUNDNUM(m10 * boxes_params[i].x1 + m11 * boxes_params[i].y1 + m12);
    out_params[i].x2 = UPM_ROUNDNUM(m00 * boxes_params[i].x2 + m01 * boxes_params[i].y2 + m02);
    out_params[i].y2 = UPM_ROUNDNUM(m10 * boxes_params[i].x2 + m11 * boxes_params[i].y2 + m12);
    out_params[i].boxRadius = UPM_ROUNDNUM(s * boxes_params[i].boxRadius);
  }
}

/**
 * @brief Computes the Box Average Difference, measuring the difference of gray level in the two
 * square regions.
 * @param box_params The weak-learner parameter defining the size and locations of each box.
 * @param integral_img The integral image used to compute the average gray value in the square regions.
 * @return The difference of gray level in the two squares defined by box_params
 */
static inline float computeBadResponse(const BAD::BoxPairParams &box_params,
                                       const cv::Mat &integral_img) {
  assert(!integral_img.empty());
  assert(integral_img.type() == CV_32SC1);

  int frame_w, frame_h, box1x1, box1y1, box1x2, box1y2, box2x1, box2y1, box2x2, box2y2;
  int A, B, C, D;
  int box_area1, box_area2;
  float sum1, sum2, average1, average2;
  // Since the integral image has one extra row and col, calculate the patch dimensions
  frame_w = integral_img.cols;
  frame_h = integral_img.rows;

  // For the first box, we calculate its margin coordinates
  box1x1 = box_params.x1 - box_params.boxRadius;
  if (box1x1 < 0)
    box1x1 = 0;
  else if (box1x1 >= frame_w - 1)
    box1x1 = frame_w - 2;
  box1y1 = box_params.y1 - box_params.boxRadius;
  if (box1y1 < 0)
    box1y1 = 0;
  else if (box1y1 >= frame_h - 1)
    box1y1 = frame_h - 2;
  box1x2 = box_params.x1 + box_params.boxRadius + 1;
  if (box1x2 <= 0)
    box1x2 = 1;
  else if (box1x2 >= frame_w)
    box1x2 = frame_w - 1;
  box1y2 = box_params.y1 + box_params.boxRadius + 1;
  if (box1y2 <= 0)
    box1y2 = 1;
  else if (box1y2 >= frame_h)
    box1y2 = frame_h - 1;
  assert((box1x1 < box1x2 && box1y1 < box1y2) && "Box 1 has size 0");

  // For the second box, we calculate its margin coordinates
  box2x1 = box_params.x2 - box_params.boxRadius;
  if (box2x1 < 0)
    box2x1 = 0;
  else if (box2x1 >= frame_w - 1)
    box2x1 = frame_w - 2;
  box2y1 = box_params.y2 - box_params.boxRadius;
  if (box2y1 < 0)
    box2y1 = 0;
  else if (box2y1 >= frame_h - 1)
    box2y1 = frame_h - 2;
  box2x2 = box_params.x2 + box_params.boxRadius + 1;
  if (box2x2 <= 0)
    box2x2 = 1;
  else if (box2x2 >= frame_w)
    box2x2 = frame_w - 1;
  box2y2 = box_params.y2 + box_params.boxRadius + 1;
  if (box2y2 <= 0)
    box2y2 = 1;
  else if (box2y2 >= frame_h)
    box2y2 = frame_h - 1;
  assert((box2x1 < box2x2 && box2y1 < box2y2) && "Box 2 has size 0");

  // Read the integral image values for the first box
  A = integral_img.at<int>(box1y1, box1x1);
  B = integral_img.at<int>(box1y1, box1x2);
  C = integral_img.at<int>(box1y2, box1x1);
  D = integral_img.at<int>(box1y2, box1x2);

  // Calculate the mean intensity value of the pixels in the box
  sum1 = static_cast<float>(A + D - B - C);
  box_area1 = (box1y2 - box1y1) * (box1x2 - box1x1);
  assert(box_area1 > 0);
  average1 = sum1 / box_area1;

  // Calculate the indices on the integral image where the box falls
  A = integral_img.at<int>(box2y1, box2x1);
  B = integral_img.at<int>(box2y1, box2x2);
  C = integral_img.at<int>(box2y2, box2x1);
  D = integral_img.at<int>(box2y2, box2x2);

  // Calculate the mean intensity value of the pixels in the box
  sum2 = static_cast<float>(A + D - B - C);
  box_area2 = (box2y2 - box2y1) * (box2x2 - box2x1);
  assert(box_area2 > 0);
  average2 = sum2 / box_area2;

  return average1 - average2;
}

/**
 * @brief Function that determines if a keypoint is close to the image border.
 * @param kp The detected keypoint
 * @param img_size The size of the image
 * @param patch_size The size of the normalized patch where the measurement functions were learnt.
 * @param scale_factor A scale factor that magnifies the measurement functions w.r.t. the keypoint.
 * @return true if the keypoint is in the border, false otherwise
 */
static inline bool isKeypointInTheBorder(const cv::KeyPoint &kp,
                                         const cv::Size &img_size,
                                         const cv::Size &patch_size = {32, 32},
                                         float scale_factor = 1) {
  // This would be the correct measure but since we will compare with half of the size, use this as border size
  float s = scale_factor * kp.size / (patch_size.width + patch_size.height);
  cv::Size2f border(patch_size.width * s * UPM_BAD_EXTRA_RATIO_MARGIN,
                    patch_size.height * s * UPM_BAD_EXTRA_RATIO_MARGIN);

  if (kp.pt.x < border.width || kp.pt.x + border.width >= img_size.width)
    return true;

  if (kp.pt.y < border.height || kp.pt.y + border.height >= img_size.height)
    return true;

  return false;
}

///////////////////////////////////////////////////////////////////////////////

BAD::BAD(float scale_factor, BadSize n_bits) {
  scale_factor_ = scale_factor;

  if (n_bits == SIZE_512_BITS) {
    // With data augmentation
    // box_params_ = {{17,18,12,15,2}, {13,14,5,7,5}, {21,16,16,14,1}, {27,11,18,20,3}, {17,13,16,19,2},
    // {18,24,18,16,5}, {12,11,10,25,6}, {14,17,14,13,1}, {7,4,4,15,4}, {27,27,23,8,4}, {19,13,19,6,6}, {14,15,10,16,1},
    // {13,15,12,22,1}, {8,22,3,27,3}, {13,19,8,13,1}, {18,16,17,12,1}, {27,7,25,11,4}, {24,20,20,15,2}, {16,24,14,3,3},
    // {23,18,7,18,7}, {8,7,2,1,1}, {17,28,17,26,3}, {17,13,17,10,2}, {10,18,10,11,1}, {11,28,7,22,2}, {18,13,15,15,1},
    // {7,14,3,20,3}, {17,19,14,15,1}, {14,12,14,8,2}, {14,12,13,11,1}, {21,9,19,19,2}, {4,28,3,10,3}, {27,27,26,26,4},
    // {19,22,19,19,2}, {12,25,12,20,1}, {19,12,15,12,1}, {28,21,23,21,2}, {10,15,7,18,2}, {12,7,10,3,3},
    // {21,16,19,15,1}, {19,20,18,17,1}, {26,2,19,7,2}, {18,2,15,22,2}, {24,26,24,22,5}, {15,26,15,19,1},
    // {13,19,11,20,1}, {5,14,4,10,4}, {15,7,15,4,2}, {13,16,11,7,1}, {15,22,15,18,1}, {24,8,23,4,4}, {13,11,11,14,1},
    // {4,19,3,19,3}, {22,12,19,10,1}, {24,27,15,22,2}, {12,13,10,10,1}, {11,25,9,29,2}, {15,21,15,10,1},
    // {19,16,18,19,1}, {29,13,24,8,2}, {17,16,16,20,1}, {12,17,12,15,1}, {28,4,2,11,2}, {7,25,5,19,3}, {22,13,20,16,1},
    // {14,16,13,17,1}, {10,3,8,11,3}, {18,7,17,11,2}, {27,11,25,22,2}, {5,26,3,28,3}, {28,13,27,13,3}, {22,20,20,28,3},
    // {12,6,5,2,2}, {14,18,13,16,1}, {17,29,3,25,2}, {20,20,19,19,1}, {15,12,14,15,1}, {12,14,12,13,1},
    // {17,14,10,26,3}, {11,15,6,12,6}, {9,22,9,19,1}, {19,18,19,14,1}, {23,15,12,18,2}, {12,15,11,14,1}, {28,2,27,9,2},
    // {11,19,11,11,7}, {13,29,13,23,2}, {27,19,22,17,3}, {17,3,17,2,2}, {4,6,3,3,3}, {19,15,16,16,1}, {22,5,20,9,2},
    // {14,6,13,9,2}, {17,16,13,16,2}, {24,18,12,6,6}, {20,14,18,15,2}, {20,9,18,13,1}, {18,20,17,8,2}, {10,15,9,15,2},
    // {13,7,12,26,2}, {13,12,11,19,2}, {15,2,2,29,2}, {15,12,14,13,1}, {20,30,19,26,1}, {28,26,28,4,3},
    // {16,13,15,12,1}, {18,11,17,25,2}, {3,17,1,24,1}, {21,18,19,22,1}, {9,13,9,8,2}, {19,18,16,16,1}, {21,22,17,20,1},
    // {13,4,13,3,3}, {24,15,21,9,1}, {24,25,19,17,6}, {4,14,3,14,2}, {17,13,14,19,1}, {7,19,4,16,3}, {4,20,1,5,1},
    // {15,13,12,14,3}, {19,26,19,21,2}, {11,26,10,18,5}, {17,16,17,13,1}, {19,16,19,11,1}, {4,26,4,23,4},
    // {14,19,14,13,5}, {10,13,8,13,2}, {14,12,14,10,1}, {29,24,26,19,2}, {26,9,19,19,5}, {16,23,16,17,1}, {4,13,3,4,3},
    // {13,16,7,21,2}, {17,16,16,17,1}, {29,15,5,18,2}, {29,2,23,5,2}, {9,17,9,14,2}, {25,26,25,22,5}, {13,21,13,20,1},
    // {23,12,7,20,6}, {6,8,6,3,3}, {13,19,13,17,1}, {25,21,22,20,1}, {24,17,23,15,2}, {20,8,17,4,1}, {11,19,10,17,1},
    // {9,11,6,9,1}, {25,9,24,14,1}, {18,20,13,14,3}, {26,23,25,23,5}, {14,20,11,4,4}, {28,7,25,13,3}, {13,13,12,12,1},
    // {7,29,2,2,2}, {16,17,16,8,5}, {20,6,19,12,3}, {19,7,19,6,6}, {20,13,19,14,1}, {19,24,16,29,2}, {8,15,4,13,1},
    // {7,9,2,10,2}, {15,14,14,13,1}, {18,13,18,11,1}, {8,19,5,23,2}, {3,13,1,14,1}, {23,20,16,14,1}, {17,15,13,18,2},
    // {16,16,9,14,5}, {15,28,15,27,3}, {18,20,16,19,1}, {16,17,16,11,2}, {30,1,10,19,1}, {12,19,9,23,2},
    // {25,13,21,13,1}, {9,23,5,24,5}, {13,20,13,18,1}, {13,13,12,13,3}, {29,18,25,2,2}, {30,30,25,26,1},
    // {16,20,15,11,1}, {18,16,18,14,1}, {15,18,5,7,4}, {16,13,15,19,1}, {26,24,16,9,5}, {1,28,1,5,1}, {20,17,20,16,1},
    // {15,19,10,17,4}, {12,9,10,5,1}, {30,29,28,29,1}, {29,17,27,18,2}, {17,29,15,27,2}, {9,29,9,28,2},
    // {23,24,21,22,1}, {22,2,1,1,1}, {20,4,20,1,1}, {5,30,4,25,1}, {20,8,17,12,7}, {10,7,3,17,3}, {21,17,14,15,5},
    // {14,10,13,8,1}, {4,21,4,13,3}, {30,1,24,10,1}, {15,17,14,16,3}, {21,23,20,15,3}, {17,20,17,18,3}, {12,11,12,6,5},
    // {15,15,12,17,1}, {25,9,16,25,6}, {22,28,22,27,3}, {5,8,3,3,3}, {9,5,9,1,1}, {30,12,29,23,1}, {20,21,5,9,5},
    // {15,21,15,20,1}, {11,17,10,23,2}, {16,11,15,13,1}, {16,12,16,10,1}, {15,6,14,3,3}, {2,4,1,1,1}, {15,16,11,15,1},
    // {24,6,24,2,2}, {8,15,6,12,1}, {21,27,1,30,1}, {17,10,14,16,3}, {13,9,7,7,7}, {22,17,19,17,1}, {16,14,14,13,2},
    // {14,21,13,23,1}, {18,2,15,7,2}, {3,25,1,24,1}, {24,20,7,14,7}, {26,25,24,19,2}, {6,25,6,23,6}, {15,24,15,17,7},
    // {22,14,16,15,1}, {17,25,17,23,1}, {12,18,2,26,2}, {30,30,26,11,1}, {22,8,16,14,5}, {9,16,8,20,1}, {4,14,2,13,2},
    // {28,7,27,8,1}, {10,22,9,24,1}, {14,16,13,18,3}, {28,26,3,15,2}, {12,15,10,15,1}, {18,17,17,15,1},
    // {30,10,28,14,1}, {30,14,28,30,1}, {30,18,7,13,1}, {3,19,2,20,1}, {16,19,14,13,2}, {11,9,5,27,4}, {16,19,15,15,2},
    // {24,22,18,19,7}, {12,17,12,12,1}, {28,5,28,1,1}, {4,29,2,30,1}, {27,11,27,8,1}, {8,3,8,1,1}, {15,10,15,8,3},
    // {12,27,11,18,4}, {25,6,22,8,6}, {15,3,15,2,2}, {19,22,17,19,1}, {24,21,24,16,2}, {9,7,6,6,6}, {13,26,11,27,2},
    // {24,10,19,12,4}, {22,17,22,9,2}, {17,14,14,11,1}, {13,4,13,3,1}, {15,18,15,17,1}, {29,30,29,24,1},
    // {29,29,20,17,2}, {6,12,2,27,2}, {18,17,14,13,2}, {11,27,11,26,4}, {22,12,3,18,3}, {15,13,13,9,1}, {12,20,7,18,1},
    // {16,6,15,9,1}, {3,6,1,7,1}, {12,17,11,19,1}, {15,8,8,18,7}, {11,19,11,5,3}, {17,20,16,23,3}, {12,6,9,13,1},
    // {2,1,1,2,1}, {14,26,13,21,3}, {25,16,16,14,3}, {30,14,29,14,1}, {27,25,15,22,4}, {13,10,8,7,2}, {18,19,13,14,1},
    // {28,28,28,22,3}, {8,14,8,11,1}, {23,28,22,24,2}, {8,2,3,18,2}, {22,24,22,23,7}, {20,17,15,16,1}, {8,11,6,4,4},
    // {25,13,23,13,2}, {18,18,16,15,1}, {20,16,16,15,1}, {18,20,14,26,3}, {17,12,17,8,1}, {1,5,1,3,1}, {22,13,13,20,2},
    // {17,16,17,14,3}, {27,17,25,17,2}, {8,23,6,29,2}, {15,4,14,18,1}, {10,24,10,17,4}, {25,30,25,28,1}, {3,22,1,29,1},
    // {24,8,23,17,1}, {26,3,26,1,1}, {18,22,18,17,2}, {9,17,8,10,2}, {29,22,29,2,2}, {19,4,5,10,3}, {3,28,3,27,1},
    // {12,15,11,18,1}, {30,3,28,4,1}, {7,9,7,8,1}, {24,15,8,14,7}, {30,6,20,16,1}, {18,18,1,10,1}, {30,20,28,21,1},
    // {15,15,13,14,1}, {6,3,5,1,1}, {3,8,1,17,1}, {3,2,2,2,2}, {19,28,18,20,1}, {20,20,20,17,2}, {21,30,19,29,1},
    // {12,19,12,13,1}, {29,10,29,4,2}, {20,16,20,14,1}, {15,9,11,16,2}, {8,13,6,26,4}, {13,11,12,8,2}, {17,27,17,26,4},
    // {29,29,14,12,1}, {29,2,28,3,2}, {9,15,7,9,4}, {27,28,12,30,1}, {14,30,2,28,1}, {19,12,18,14,1}, {26,5,24,15,5},
    // {2,24,2,2,2}, {6,21,5,21,1}, {22,16,9,17,2}, {16,19,15,17,1}, {2,29,2,28,2}, {25,11,24,1,1}, {16,30,16,29,1},
    // {14,20,14,17,3}, {15,14,11,17,3}, {18,17,16,21,1}, {17,8,17,4,2}, {11,4,11,3,3}, {25,16,9,17,6}, {18,8,18,6,6},
    // {17,22,17,19,1}, {8,20,3,11,3}, {20,17,4,17,1}, {29,12,12,19,2}, {14,29,14,28,2}, {12,18,10,18,1},
    // {13,15,13,11,2}, {18,15,14,15,2}, {19,17,17,19,1}, {22,17,12,16,6}, {30,22,29,18,1}, {30,2,29,20,1},
    // {12,3,1,1,1}, {4,7,1,7,1}, {27,10,21,13,4}, {18,21,18,13,3}, {12,4,3,6,2}, {12,10,9,3,2}, {3,28,2,29,2},
    // {22,2,20,5,2}, {27,18,20,3,3}, {6,24,6,23,1}, {27,26,9,16,4}, {5,18,5,11,5}, {20,14,15,12,3}, {19,16,19,15,1},
    // {27,4,21,9,4}, {3,19,2,29,1}, {20,24,18,22,1}, {18,7,18,2,1}, {28,30,28,28,1}, {11,24,10,9,1}, {21,18,21,14,3},
    // {27,19,26,18,2}, {16,18,10,6,6}, {11,18,5,19,1}, {24,16,22,16,1}, {17,15,17,9,5}, {27,29,20,11,2},
    // {29,25,28,22,1}, {21,11,21,5,1}, {12,15,8,16,2}, {2,29,1,30,1}, {18,12,4,21,3}, {18,9,11,13,3}, {18,3,10,21,3},
    // {17,11,16,16,1}, {15,17,13,14,1}, {7,7,7,5,5}, {9,29,5,18,2}, {10,11,10,6,6}, {28,26,25,26,1}, {19,30,8,20,1},
    // {8,15,7,29,2}, {21,18,19,17,1}, {2,22,1,22,1}, {12,20,4,17,1}, {27,8,4,14,2}, {26,10,25,13,1}, {19,13,19,8,3},
    // {12,16,7,18,7}, {20,26,12,3,3}, {6,10,3,10,2}, {25,25,25,21,2}, {12,3,7,16,2}, {8,4,4,17,4}, {12,20,5,8,5},
    // {22,15,8,13,7}, {12,13,12,8,2}, {20,15,19,13,1}, {30,5,29,8,1}, {14,29,13,23,2}, {18,19,9,10,7}, {2,11,1,10,1},
    // {12,13,12,11,1}, {27,15,9,5,4}, {13,12,7,17,2}, {8,17,1,26,1}, {20,24,11,12,4}, {12,24,10,22,6}, {19,29,14,20,1},
    // {20,27,20,25,2}, {9,25,8,27,1}, {7,11,5,11,1}, {20,11,11,8,1}, {9,8,9,5,1}, {27,9,25,10,1}, {30,20,22,20,1},
    // {26,21,26,20,1}, {30,14,27,16,1}, {12,16,11,19,3}, {7,28,6,29,1}, {17,23,17,22,2}, {12,17,2,2,1},
    // {17,14,17,13,1}, {18,12,16,16,1}, {7,23,7,17,1}, {25,12,9,15,4}, {16,6,16,5,5}, {8,16,7,16,7}, {6,7,5,7,5},
    // {15,13,15,12,2}, {13,15,13,13,3}, {16,12,16,11,1}, {18,15,15,14,3}, {17,8,14,5,4}, {9,26,6,22,5},
    // {17,16,14,17,3}, {25,1,24,2,1}, {14,16,14,15,1}, {24,22,4,23,4}, {30,29,27,29,1}, {17,18,17,17,1},
    // {19,30,19,28,1}, {21,27,21,23,3}, {16,18,15,20,1}, {27,27,13,12,4}, {30,25,27,26,1}, {4,21,3,7,1}, {10,5,10,4,4},
    // {14,14,5,3,1}, {23,6,21,3,3}, {9,20,2,15,2}, {23,9,20,13,1}, {15,14,12,3,3}, {19,25,19,18,4}, {27,25,24,22,4},
    // {15,15,15,11,1}, {17,16,14,13,1}, {12,18,12,17,1}, {30,3,30,2,1}, {21,20,18,28,3}, {25,25,7,14,5}, {3,11,2,3,2},
    // {25,5,9,21,4}, {6,15,4,28,3}, {9,9,3,3,3}, {16,19,14,16,2}, {10,25,10,20,1}, {2,17,2,15,1}, {17,15,15,16,1},
    // {20,15,19,15,1}, {22,2,22,1,1}, {15,19,15,18,1}, {15,16,10,12,1}, {28,2,23,14,2}, {11,3,9,2,1}}; thresholds_ =
    // {14.45,4.15,7.75,9.65,2.25,0.15,0.45,-0.95,3.65,-1.75,1.05,5.45,-0.05,-2.65,3.35,1.65,-1.55,2.85,3.05,22.05,
    // -3.65,-0.15,-0.55,-0.05,3.25,-2.85,-1.25,10.45,-1.05,1.25,3.15,2.05,-0.55,-1.25,3.45,4.35,2.45,2.55,1.35,1.25,
    // 2.75,-0.15,8.35,0.35,-1.25,0.75,-0.45,-0.05,0.85,3.65,1.55,1.75,-0.35,1.35,4.85,-2.25,0.25,-2.15,3.35,1.95,6.25,
    // 0.35,24.45,-1.15,0.85,-1.95,5.15,1.35,0.85,0.35,-0.45,4.95,-0.25,2.45,11.75,0.85,-1.65,0.05,4.05,-0.35,-0.95,
    // -0.25,49.35,0.85,1.95,0.25,1.15,-2.65,-0.25,0.85,-5.65,1.15,3.05,4.05,7.35,9.05,0.35,1.65,1.65,2.55,6.95,1.75,
    // 0.85,-1.15,1.35,5.45,1.35,-2.35,-0.15,0.85,-3.05,0.05,-0.35,-0.65,11.65,-0.85,1.15,2.35,-9.25,16.05,-1.45,1.95,
    // 0.35,-0.35,0.15,0.25,-1.35,0.65,-4.05,-2.25,1.05,-0.05,-1.55,0.25,69.45,0.15,-1.25,-1.85,-0.65,8.75,-0.95,1.95,
    // 1.05,-1.45,2.15,-1.85,-1.75,-2.95,2.65,0.65,-1.05,4.35,0.25,19.65,0.35,1.65,0.65,2.75,2.85,-10.95,3.65,-4.15,
    // 0.25,-0.65,-2.25,3.75,35.75,3.15,-0.55,1.95,-6.55,88.35,7.25,1.75,-4.15,0.25,0.25,0.65,3.75,1.65,2.85,42.15,
    // 11.75, -1.25,-8.25,0.05,2.15,0.65,-1.55,-2.75,1.15,-0.15,-0.75,16.85,1.15,1.45,15.35,19.45,8.65,-1.25,0.25,
    // 2.15,0.15,2.85, -2.25,1.75,-15.15,4.15,-0.45,-8.25,1.25,-0.85,3.55,0.45,-1.25,9.65,1.25,3.15,-2.05,-6.85,-0.05,
    // 3.25,7.05,2.35, -1.45,-1.05,20.25,1.15,1.35,1.05,5.15,2.55,0.55,0.55,-0.15,0.65,-28.35,3.85,2.05,-1.15,3.05,
    // -0.95,-1.55,-0.35, 101.95,0.35,-2.05,-2.15,4.25,105.15,1.15,27.45,30.15,18.45,-2.45,1.85,2.95,-3.75,-0.65,0.05,
    // 0.25,34.45,-2.05, 0.25,3.25,2.05,2.85,3.45,20.95,1.45,-1.95,-0.35,-6.85,1.15,-31.95,11.85,2.75,0.15,8.35,1.15,
    // 2.15,-1.15,-1.05, 2.45,1.45,0.15,-1.65,41.85,0.35,0.65,-0.35,0.25,56.75,23.55,88.85,-7.25,1.05,0.75,-1.05,-1.65,
    // -9.75,-16.95,-0.05, -10.05,34.15,14.75,-0.95,1.45,4.85,-0.05,-0.35,0.75,64.75,24.25,-0.35,-13.65,2.85,1.75,
    // -0.35,0.25,-12.15,108.05, -0.35,-3.35,1.95,-0.35,21.25,-20.05,95.85,-1.05,-17.75,-0.55,2.75,0.65,0.75,-1.85,
    // 2.65,-2.15,1.05,-0.05,4.25,3.75, -13.55,-0.05,105.95,0.45,3.05,9.35,79.25,1.75,7.65,-0.45,0.95,79.15,28.05,0.05,
    // 0.65,-0.35,0.95,2.05,1.15,2.75, -1.65,8.65,3.55,-0.25,-28.95,-7.35,122.25,0.55,4.75,1.75,11.15,0.15,2.55,0.05,
    // -7.95,51.05,6.25,0.05,-1.15,0.75, 26.65,-1.25,1.15,-0.55,0.05,5.85,1.55,2.25,-1.65,-16.85,-62.65,-1.25,-1.05,
    // -1.55,1.35,0.25,-0.65,0.85,17.45, 0.25, -9.35,34.35,0.95,-0.95,-10.05,1.45,-6.05,93.25,3.15,-10.85,-1.65,-0.15,
    // -2.45,-0.35,0.15,118.15,-81.85,4.05,1.05, -0.85,152.35,0.65,1.35,-12.35,95.35,-23.25,-0.75,75.65,50.85,47.85,
    // 2.55,0.55,0.15,0.25,38.15,-2.65,-1.95,-1.05, 110.25,35.25,2.65,3.65,18.75,89.45,-0.55,0.35,0.25,105.05,0.25,
    // 1.25,-34.65,-0.55,-0.15,0.75,-0.15,-0.15,-94.25, -12.05,-15.35,-1.75,31.35,0.15,-2.15,-0.15,-12.05,-0.35,-0.65,
    // -0.55,28.95,39.05,7.05,0.65,-1.65,2.85,4.85,-1.85, 1.75,-31.65,0.05,13.75,-0.35,0.35,-5.75,83.85,0.95,27.95,
    // -0.25,-19.05,2.45,-13.25,44.05,51.85,-0.05,0.05,79.35,111.25,-61.65,3.05,-69.95,35.65,62.05,-0.25,-1.05,-2.95,
    // 0.95,-0.15,-18.15,-18.65,74.55,2.65};

    // Without data augmentation
    box_params_ = {
      {17, 12, 18, 15, 2}, {13, 5, 14, 7, 5},   {21, 16, 16, 14, 1}, {27, 18, 11, 20, 3}, {17, 16, 13, 19, 2},
      {18, 18, 24, 16, 5}, {12, 10, 11, 25, 6}, {14, 14, 17, 13, 1}, {7, 4, 4, 15, 4},    {27, 23, 27, 8, 4},
      {19, 19, 13, 6, 6},  {14, 10, 15, 16, 1}, {13, 12, 15, 22, 1}, {8, 3, 22, 27, 3},   {13, 8, 19, 13, 1},
      {18, 17, 16, 12, 1}, {27, 25, 7, 11, 4},  {24, 20, 20, 15, 2}, {16, 14, 24, 3, 3},  {23, 7, 18, 18, 7},
      {8, 2, 7, 1, 1},     {17, 17, 28, 26, 3}, {17, 17, 13, 10, 2}, {10, 10, 18, 11, 1}, {11, 7, 28, 22, 2},
      {18, 15, 13, 15, 1}, {7, 3, 14, 20, 3},   {17, 14, 19, 15, 1}, {14, 14, 12, 8, 2},  {14, 13, 12, 11, 1},
      {21, 19, 9, 19, 2},  {4, 3, 28, 10, 3},   {27, 26, 27, 26, 4}, {19, 19, 22, 19, 2}, {12, 12, 25, 20, 1},
      {19, 15, 12, 12, 1}, {28, 23, 21, 21, 2}, {10, 7, 15, 18, 2},  {12, 10, 7, 3, 3},   {21, 19, 16, 15, 1},
      {19, 18, 20, 17, 1}, {26, 19, 2, 7, 2},   {18, 15, 2, 22, 2},  {24, 24, 26, 22, 5}, {15, 15, 26, 19, 1},
      {13, 11, 19, 20, 1}, {5, 4, 14, 10, 4},   {15, 15, 7, 4, 2},   {13, 11, 16, 7, 1},  {15, 15, 22, 18, 1},
      {24, 23, 8, 4, 4},   {13, 11, 11, 14, 1}, {4, 3, 19, 19, 3},   {22, 19, 12, 10, 1}, {24, 15, 27, 22, 2},
      {12, 10, 13, 10, 1}, {11, 9, 25, 29, 2},  {15, 15, 21, 10, 1}, {19, 18, 16, 19, 1}, {29, 24, 13, 8, 2},
      {17, 16, 16, 20, 1}, {12, 12, 17, 15, 1}, {28, 2, 4, 11, 2},   {7, 5, 25, 19, 3},   {22, 20, 13, 16, 1},
      {14, 13, 16, 17, 1}, {10, 8, 3, 11, 3},   {18, 17, 7, 11, 2},  {27, 25, 11, 22, 2}, {5, 3, 26, 28, 3},
      {28, 27, 13, 13, 3}, {22, 20, 20, 28, 3}, {12, 5, 6, 2, 2},    {14, 13, 18, 16, 1}, {17, 3, 29, 25, 2},
      {20, 19, 20, 19, 1}, {15, 14, 12, 15, 1}, {12, 12, 14, 13, 1}, {17, 10, 14, 26, 3}, {11, 6, 15, 12, 6},
      {9, 9, 22, 19, 1},   {19, 19, 18, 14, 1}, {23, 12, 15, 18, 2}, {12, 11, 15, 14, 1}, {28, 27, 2, 9, 2},
      {11, 11, 19, 11, 7}, {13, 13, 29, 23, 2}, {27, 22, 19, 17, 3}, {17, 17, 3, 2, 2},   {4, 3, 6, 3, 3},
      {19, 16, 15, 16, 1}, {22, 20, 5, 9, 2},   {14, 13, 6, 9, 2},   {17, 13, 16, 16, 2}, {24, 12, 18, 6, 6},
      {20, 18, 14, 15, 2}, {20, 18, 9, 13, 1},  {18, 17, 20, 8, 2},  {10, 9, 15, 15, 2},  {13, 12, 7, 26, 2},
      {13, 11, 12, 19, 2}, {15, 2, 2, 29, 2},   {15, 14, 12, 13, 1}, {20, 19, 30, 26, 1}, {28, 28, 26, 4, 3},
      {16, 15, 13, 12, 1}, {18, 17, 11, 25, 2}, {3, 1, 17, 24, 1},   {21, 19, 18, 22, 1}, {9, 9, 13, 8, 2},
      {19, 16, 18, 16, 1}, {21, 17, 22, 20, 1}, {13, 13, 4, 3, 3},   {24, 21, 15, 9, 1},  {24, 19, 25, 17, 6},
      {4, 3, 14, 14, 2},   {17, 14, 13, 19, 1}, {7, 4, 19, 16, 3},   {4, 1, 20, 5, 1},    {15, 12, 13, 14, 3},
      {19, 19, 26, 21, 2}, {11, 10, 26, 18, 5}, {17, 17, 16, 13, 1}, {19, 19, 16, 11, 1}, {4, 4, 26, 23, 4},
      {14, 14, 19, 13, 5}, {10, 8, 13, 13, 2},  {14, 14, 12, 10, 1}, {29, 26, 24, 19, 2}, {26, 19, 9, 19, 5},
      {16, 16, 23, 17, 1}, {4, 3, 13, 4, 3},    {13, 7, 16, 21, 2},  {17, 16, 16, 17, 1}, {29, 5, 15, 18, 2},
      {29, 23, 2, 5, 2},   {9, 9, 17, 14, 2},   {25, 25, 26, 22, 5}, {13, 13, 21, 20, 1}, {23, 7, 12, 20, 6},
      {6, 6, 8, 3, 3},     {13, 13, 19, 17, 1}, {25, 22, 21, 20, 1}, {24, 23, 17, 15, 2}, {20, 17, 8, 4, 1},
      {11, 10, 19, 17, 1}, {9, 6, 11, 9, 1},    {25, 24, 9, 14, 1},  {18, 13, 20, 14, 3}, {26, 25, 23, 23, 5},
      {14, 11, 20, 4, 4},  {28, 25, 7, 13, 3},  {13, 12, 13, 12, 1}, {7, 2, 29, 2, 2},    {16, 16, 17, 8, 5},
      {20, 19, 6, 12, 3},  {19, 19, 7, 6, 6},   {20, 19, 13, 14, 1}, {19, 16, 24, 29, 2}, {8, 4, 15, 13, 1},
      {7, 2, 9, 10, 2},    {15, 14, 14, 13, 1}, {18, 18, 13, 11, 1}, {8, 5, 19, 23, 2},   {3, 1, 13, 14, 1},
      {23, 16, 20, 14, 1}, {17, 13, 15, 18, 2}, {16, 9, 16, 14, 5},  {15, 15, 28, 27, 3}, {18, 16, 20, 19, 1},
      {16, 16, 17, 11, 2}, {30, 10, 1, 19, 1},  {12, 9, 19, 23, 2},  {25, 21, 13, 13, 1}, {9, 5, 23, 24, 5},
      {13, 13, 20, 18, 1}, {13, 12, 13, 13, 3}, {29, 25, 18, 2, 2},  {30, 25, 30, 26, 1}, {16, 15, 20, 11, 1},
      {18, 18, 16, 14, 1}, {15, 5, 18, 7, 4},   {16, 15, 13, 19, 1}, {26, 16, 24, 9, 5},  {1, 1, 28, 5, 1},
      {20, 20, 17, 16, 1}, {15, 10, 19, 17, 4}, {12, 10, 9, 5, 1},   {30, 28, 29, 29, 1}, {29, 27, 17, 18, 2},
      {17, 15, 29, 27, 2}, {9, 9, 29, 28, 2},   {23, 21, 24, 22, 1}, {22, 1, 2, 1, 1},    {20, 20, 4, 1, 1},
      {5, 4, 30, 25, 1},   {20, 17, 8, 12, 7},  {10, 3, 7, 17, 3},   {21, 14, 17, 15, 5}, {14, 13, 10, 8, 1},
      {4, 4, 21, 13, 3},   {30, 24, 1, 10, 1},  {15, 14, 17, 16, 3}, {21, 20, 23, 15, 3}, {17, 17, 20, 18, 3},
      {12, 12, 11, 6, 5},  {15, 12, 15, 17, 1}, {25, 16, 9, 25, 6},  {22, 22, 28, 27, 3}, {5, 3, 8, 3, 3},
      {9, 9, 5, 1, 1},     {30, 29, 12, 23, 1}, {20, 5, 21, 9, 5},   {15, 15, 21, 20, 1}, {11, 10, 17, 23, 2},
      {16, 15, 11, 13, 1}, {16, 16, 12, 10, 1}, {15, 14, 6, 3, 3},   {2, 1, 4, 1, 1},     {15, 11, 16, 15, 1},
      {24, 24, 6, 2, 2},   {8, 6, 15, 12, 1},   {21, 1, 27, 30, 1},  {17, 14, 10, 16, 3}, {13, 7, 9, 7, 7},
      {22, 19, 17, 17, 1}, {16, 14, 14, 13, 2}, {14, 13, 21, 23, 1}, {18, 15, 2, 7, 2},   {3, 1, 25, 24, 1},
      {24, 7, 20, 14, 7},  {26, 24, 25, 19, 2}, {6, 6, 25, 23, 6},   {15, 15, 24, 17, 7}, {22, 16, 14, 15, 1},
      {17, 17, 25, 23, 1}, {12, 2, 18, 26, 2},  {30, 26, 30, 11, 1}, {22, 16, 8, 14, 5},  {9, 8, 16, 20, 1},
      {4, 2, 14, 13, 2},   {28, 27, 7, 8, 1},   {10, 9, 22, 24, 1},  {14, 13, 16, 18, 3}, {28, 3, 26, 15, 2},
      {12, 10, 15, 15, 1}, {18, 17, 17, 15, 1}, {30, 28, 10, 14, 1}, {30, 28, 14, 30, 1}, {30, 7, 18, 13, 1},
      {3, 2, 19, 20, 1},   {16, 14, 19, 13, 2}, {11, 5, 9, 27, 4},   {16, 15, 19, 15, 2}, {24, 18, 22, 19, 7},
      {12, 12, 17, 12, 1}, {28, 28, 5, 1, 1},   {4, 2, 29, 30, 1},   {27, 27, 11, 8, 1},  {8, 8, 3, 1, 1},
      {15, 15, 10, 8, 3},  {12, 11, 27, 18, 4}, {25, 22, 6, 8, 6},   {15, 15, 3, 2, 2},   {19, 17, 22, 19, 1},
      {24, 24, 21, 16, 2}, {9, 6, 7, 6, 6},     {13, 11, 26, 27, 2}, {24, 19, 10, 12, 4}, {22, 22, 17, 9, 2},
      {17, 14, 14, 11, 1}, {13, 13, 4, 3, 1},   {15, 15, 18, 17, 1}, {29, 29, 30, 24, 1}, {29, 20, 29, 17, 2},
      {6, 2, 12, 27, 2},   {18, 14, 17, 13, 2}, {11, 11, 27, 26, 4}, {22, 3, 12, 18, 3},  {15, 13, 13, 9, 1},
      {12, 7, 20, 18, 1},  {16, 15, 6, 9, 1},   {3, 1, 6, 7, 1},     {12, 11, 17, 19, 1}, {15, 8, 8, 18, 7},
      {11, 11, 19, 5, 3},  {17, 16, 20, 23, 3}, {12, 9, 6, 13, 1},   {2, 1, 1, 2, 1},     {14, 13, 26, 21, 3},
      {25, 16, 16, 14, 3}, {30, 29, 14, 14, 1}, {27, 15, 25, 22, 4}, {13, 8, 10, 7, 2},   {18, 13, 19, 14, 1},
      {28, 28, 28, 22, 3}, {8, 8, 14, 11, 1},   {23, 22, 28, 24, 2}, {8, 3, 2, 18, 2},    {22, 22, 24, 23, 7},
      {20, 15, 17, 16, 1}, {8, 6, 11, 4, 4},    {25, 23, 13, 13, 2}, {18, 16, 18, 15, 1}, {20, 16, 16, 15, 1},
      {18, 14, 20, 26, 3}, {17, 17, 12, 8, 1},  {1, 1, 5, 3, 1},     {22, 13, 13, 20, 2}, {17, 17, 16, 14, 3},
      {27, 25, 17, 17, 2}, {8, 6, 23, 29, 2},   {15, 14, 4, 18, 1},  {10, 10, 24, 17, 4}, {25, 25, 30, 28, 1},
      {3, 1, 22, 29, 1},   {24, 23, 8, 17, 1},  {26, 26, 3, 1, 1},   {18, 18, 22, 17, 2}, {9, 8, 17, 10, 2},
      {29, 29, 22, 2, 2},  {19, 5, 4, 10, 3},   {3, 3, 28, 27, 1},   {12, 11, 15, 18, 1}, {30, 28, 3, 4, 1},
      {7, 7, 9, 8, 1},     {24, 8, 15, 14, 7},  {30, 20, 6, 16, 1},  {18, 1, 18, 10, 1},  {30, 28, 20, 21, 1},
      {15, 13, 15, 14, 1}, {6, 5, 3, 1, 1},     {3, 1, 8, 17, 1},    {3, 2, 2, 2, 2},     {19, 18, 28, 20, 1},
      {20, 20, 20, 17, 2}, {21, 19, 30, 29, 1}, {12, 12, 19, 13, 1}, {29, 29, 10, 4, 2},  {20, 20, 16, 14, 1},
      {15, 11, 9, 16, 2},  {8, 6, 13, 26, 4},   {13, 12, 11, 8, 2},  {17, 17, 27, 26, 4}, {29, 14, 29, 12, 1},
      {29, 28, 2, 3, 2},   {9, 7, 15, 9, 4},    {27, 12, 28, 30, 1}, {14, 2, 30, 28, 1},  {19, 18, 12, 14, 1},
      {26, 24, 5, 15, 5},  {2, 2, 24, 2, 2},    {6, 5, 21, 21, 1},   {22, 9, 16, 17, 2},  {16, 15, 19, 17, 1},
      {2, 2, 29, 28, 2},   {25, 24, 11, 1, 1},  {16, 16, 30, 29, 1}, {14, 14, 20, 17, 3}, {15, 11, 14, 17, 3},
      {18, 16, 17, 21, 1}, {17, 17, 8, 4, 2},   {11, 11, 4, 3, 3},   {25, 9, 16, 17, 6},  {18, 18, 8, 6, 6},
      {17, 17, 22, 19, 1}, {8, 3, 20, 11, 3},   {20, 4, 17, 17, 1},  {29, 12, 12, 19, 2}, {14, 14, 29, 28, 2},
      {12, 10, 18, 18, 1}, {13, 13, 15, 11, 2}, {18, 14, 15, 15, 2}, {19, 17, 17, 19, 1}, {22, 12, 17, 16, 6},
      {30, 29, 22, 18, 1}, {30, 29, 2, 20, 1},  {12, 1, 3, 1, 1},    {4, 1, 7, 7, 1},     {27, 21, 10, 13, 4},
      {18, 18, 21, 13, 3}, {12, 3, 4, 6, 2},    {12, 9, 10, 3, 2},   {3, 2, 28, 29, 2},   {22, 20, 2, 5, 2},
      {27, 20, 18, 3, 3},  {6, 6, 24, 23, 1},   {27, 9, 26, 16, 4},  {5, 5, 18, 11, 5},   {20, 15, 14, 12, 3},
      {19, 19, 16, 15, 1}, {27, 21, 4, 9, 4},   {3, 2, 19, 29, 1},   {20, 18, 24, 22, 1}, {18, 18, 7, 2, 1},
      {28, 28, 30, 28, 1}, {11, 10, 24, 9, 1},  {21, 21, 18, 14, 3}, {27, 26, 19, 18, 2}, {16, 10, 18, 6, 6},
      {11, 5, 18, 19, 1},  {24, 22, 16, 16, 1}, {17, 17, 15, 9, 5},  {27, 20, 29, 11, 2}, {29, 28, 25, 22, 1},
      {21, 21, 11, 5, 1},  {12, 8, 15, 16, 2},  {2, 1, 29, 30, 1},   {18, 4, 12, 21, 3},  {18, 11, 9, 13, 3},
      {18, 10, 3, 21, 3},  {17, 16, 11, 16, 1}, {15, 13, 17, 14, 1}, {7, 7, 7, 5, 5},     {9, 5, 29, 18, 2},
      {10, 10, 11, 6, 6},  {28, 25, 26, 26, 1}, {19, 8, 30, 20, 1},  {8, 7, 15, 29, 2},   {21, 19, 18, 17, 1},
      {2, 1, 22, 22, 1},   {12, 4, 20, 17, 1},  {27, 4, 8, 14, 2},   {26, 25, 10, 13, 1}, {19, 19, 13, 8, 3},
      {12, 7, 16, 18, 7},  {20, 12, 26, 3, 3},  {6, 3, 10, 10, 2},   {25, 25, 25, 21, 2}, {12, 7, 3, 16, 2},
      {8, 4, 4, 17, 4},    {12, 5, 20, 8, 5},   {22, 8, 15, 13, 7},  {12, 12, 13, 8, 2},  {20, 19, 15, 13, 1},
      {30, 29, 5, 8, 1},   {14, 13, 29, 23, 2}, {18, 9, 19, 10, 7},  {2, 1, 11, 10, 1},   {12, 12, 13, 11, 1},
      {27, 9, 15, 5, 4},   {13, 7, 12, 17, 2},  {8, 1, 17, 26, 1},   {20, 11, 24, 12, 4}, {12, 10, 24, 22, 6},
      {19, 14, 29, 20, 1}, {20, 20, 27, 25, 2}, {9, 8, 25, 27, 1},   {7, 5, 11, 11, 1},   {20, 11, 11, 8, 1},
      {9, 9, 8, 5, 1},     {27, 25, 9, 10, 1},  {30, 22, 20, 20, 1}, {26, 26, 21, 20, 1}, {30, 27, 14, 16, 1},
      {12, 11, 16, 19, 3}, {7, 6, 28, 29, 1},   {17, 17, 23, 22, 2}, {12, 2, 17, 2, 1},   {17, 17, 14, 13, 1},
      {18, 16, 12, 16, 1}, {7, 7, 23, 17, 1},   {25, 9, 12, 15, 4},  {16, 16, 6, 5, 5},   {8, 7, 16, 16, 7},
      {6, 5, 7, 7, 5},     {15, 15, 13, 12, 2}, {13, 13, 15, 13, 3}, {16, 16, 12, 11, 1}, {18, 15, 15, 14, 3},
      {17, 14, 8, 5, 4},   {9, 6, 26, 22, 5},   {17, 14, 16, 17, 3}, {25, 24, 1, 2, 1},   {14, 14, 16, 15, 1},
      {24, 4, 22, 23, 4},  {30, 27, 29, 29, 1}, {17, 17, 18, 17, 1}, {19, 19, 30, 28, 1}, {21, 21, 27, 23, 3},
      {16, 15, 18, 20, 1}, {27, 13, 27, 12, 4}, {30, 27, 25, 26, 1}, {4, 3, 21, 7, 1},    {10, 10, 5, 4, 4},
      {14, 5, 14, 3, 1},   {23, 21, 6, 3, 3},   {9, 2, 20, 15, 2},   {23, 20, 9, 13, 1},  {15, 12, 14, 3, 3},
      {19, 19, 25, 18, 4}, {27, 24, 25, 22, 4}, {15, 15, 15, 11, 1}, {17, 14, 16, 13, 1}, {12, 12, 18, 17, 1},
      {30, 30, 3, 2, 1},   {21, 18, 20, 28, 3}, {25, 7, 25, 14, 5},  {3, 2, 11, 3, 2},    {25, 9, 5, 21, 4},
      {6, 4, 15, 28, 3},   {9, 3, 9, 3, 3},     {16, 14, 19, 16, 2}, {10, 10, 25, 20, 1}, {2, 2, 17, 15, 1},
      {17, 15, 15, 16, 1}, {20, 19, 15, 15, 1}, {22, 22, 2, 1, 1},   {15, 15, 19, 18, 1}, {15, 10, 16, 12, 1},
      {28, 23, 2, 14, 2},  {11, 9, 3, 2, 1},
    };
    thresholds_ = {
      14.45,  4.15,   7.75,   9.65,   2.25,   0.15,   0.45,   -0.95,  3.65,   -1.75,  1.05,   5.45,   -0.05,  -2.65,
      3.35,   1.65,   -1.55,  2.85,   3.05,   22.05,  -3.65,  -0.15,  -0.55,  -0.05,  3.25,   -2.85,  -1.25,  10.45,
      -1.05,  1.25,   3.15,   2.05,   -0.55,  -1.25,  3.45,   4.35,   2.45,   2.55,   1.35,   1.25,   2.75,   -0.15,
      8.35,   0.35,   -1.25,  0.75,   -0.45,  -0.05,  0.85,   3.65,   1.55,   1.75,   -0.35,  1.35,   4.85,   -2.25,
      0.25,   -2.15,  3.35,   1.95,   6.25,   0.35,   24.45,  -1.15,  0.85,   -1.95,  5.15,   1.35,   0.85,   0.35,
      -0.45,  4.95,   -0.25,  2.45,   11.75,  0.85,   -1.65,  0.05,   4.05,   -0.35,  -0.95,  -0.25,  49.35,  0.85,
      1.95,   0.25,   1.15,   -2.65,  -0.25,  0.85,   -5.65,  1.15,   3.05,   4.05,   7.35,   9.05,   0.35,   1.65,
      1.65,   2.55,   6.95,   1.75,   0.85,   -1.15,  1.35,   5.45,   1.35,   -2.35,  -0.15,  0.85,   -3.05,  0.05,
      -0.35,  -0.65,  11.65,  -0.85,  1.15,   2.35,   -9.25,  16.05,  -1.45,  1.95,   0.35,   -0.35,  0.15,   0.25,
      -1.35,  0.65,   -4.05,  -2.25,  1.05,   -0.05,  -1.55,  0.25,   69.45,  0.15,   -1.25,  -1.85,  -0.65,  8.75,
      -0.95,  1.95,   1.05,   -1.45,  2.15,   -1.85,  -1.75,  -2.95,  2.65,   0.65,   -1.05,  4.35,   0.25,   19.65,
      0.35,   1.65,   0.65,   2.75,   2.85,   -10.95, 3.65,   -4.15,  0.25,   -0.65,  -2.25,  3.75,   35.75,  3.15,
      -0.55,  1.95,   -6.55,  88.35,  7.25,   1.75,   -4.15,  0.25,   0.25,   0.65,   3.75,   1.65,   2.85,   42.15,
      11.75,  -1.25,  -8.25,  0.05,   2.15,   0.65,   -1.55,  -2.75,  1.15,   -0.15,  -0.75,  16.85,  1.15,   1.45,
      15.35,  19.45,  8.65,   -1.25,  0.25,   2.15,   0.15,   2.85,   -2.25,  1.75,   -15.15, 4.15,   -0.45,  -8.25,
      1.25,   -0.85,  3.55,   0.45,   -1.25,  9.65,   1.25,   3.15,   -2.05,  -6.85,  -0.05,  3.25,   7.05,   2.35,
      -1.45,  -1.05,  20.25,  1.15,   1.35,   1.05,   5.15,   2.55,   0.55,   0.55,   -0.15,  0.65,   -28.35, 3.85,
      2.05,   -1.15,  3.05,   -0.95,  -1.55,  -0.35,  101.95, 0.35,   -2.05,  -2.15,  4.25,   105.15, 1.15,   27.45,
      30.15,  18.45,  -2.45,  1.85,   2.95,   -3.75,  -0.65,  0.05,   0.25,   34.45,  -2.05,  0.25,   3.25,   2.05,
      2.85,   3.45,   20.95,  1.45,   -1.95,  -0.35,  -6.85,  1.15,   -31.95, 11.85,  2.75,   0.15,   8.35,   1.15,
      2.15,   -1.15,  -1.05,  2.45,   1.45,   0.15,   -1.65,  41.85,  0.35,   0.65,   -0.35,  0.25,   56.75,  23.55,
      88.85,  -7.25,  1.05,   0.75,   -1.05,  -1.65,  -9.75,  -16.95, -0.05,  -10.05, 34.15,  14.75,  -0.95,  1.45,
      4.85,   -0.05,  -0.35,  0.75,   64.75,  24.25,  -0.35,  -13.65, 2.85,   1.75,   -0.35,  0.25,   -12.15, 108.05,
      -0.35,  -3.35,  1.95,   -0.35,  21.25,  -20.05, 95.85,  -1.05,  -17.75, -0.55,  2.75,   0.65,   0.75,   -1.85,
      2.65,   -2.15,  1.05,   -0.05,  4.25,   3.75,   -13.55, -0.05,  105.95, 0.45,   3.05,   9.35,   79.25,  1.75,
      7.65,   -0.45,  0.95,   79.15,  28.05,  0.05,   0.65,   -0.35,  0.95,   2.05,   1.15,   2.75,   -1.65,  8.65,
      3.55,   -0.25,  -28.95, -7.35,  122.25, 0.55,   4.75,   1.75,   11.15,  0.15,   2.55,   0.05,   -7.95,  51.05,
      6.25,   0.05,   -1.15,  0.75,   26.65,  -1.25,  1.15,   -0.55,  0.05,   5.85,   1.55,   2.25,   -1.65,  -16.85,
      -62.65, -1.25,  -1.05,  -1.55,  1.35,   0.25,   -0.65,  0.85,   17.45,  0.25,   -9.35,  34.35,  0.95,   -0.95,
      -10.05, 1.45,   -6.05,  93.25,  3.15,   -10.85, -1.65,  -0.15,  -2.45,  -0.35,  0.15,   118.15, -81.85, 4.05,
      1.05,   -0.85,  152.35, 0.65,   1.35,   -12.35, 95.35,  -23.25, -0.75,  75.65,  50.85,  47.85,  2.55,   0.55,
      0.15,   0.25,   38.15,  -2.65,  -1.95,  -1.05,  110.25, 35.25,  2.65,   3.65,   18.75,  89.45,  -0.55,  0.35,
      0.25,   105.05, 0.25,   1.25,   -34.65, -0.55,  -0.15,  0.75,   -0.15,  -0.15,  -94.25, -12.05, -15.35, -1.75,
      31.35,  0.15,   -2.15,  -0.15,  -12.05, -0.35,  -0.65,  -0.55,  28.95,  39.05,  7.05,   0.65,   -1.65,  2.85,
      4.85,   -1.85,  1.75,   -31.65, 0.05,   13.75,  -0.35,  0.35,   -5.75,  83.85,  0.95,   27.95,  -0.25,  -19.05,
      2.45,   -13.25, 44.05,  51.85,  -0.05,  0.05,   79.35,  111.25, -61.65, 3.05,   -69.95, 35.65,  62.05,  -0.25,
      -1.05,  -2.95,  0.95,   -0.15,  -18.15, -18.65, 74.55,  2.65};
  } else {
    // With data augmentation
    // box_params_ = {};
    // thresholds_ = {};

    // Without data augmentation
    box_params_ = {
      {25, 13, 14, 15, 6}, {16, 14, 15, 11, 1}, {14, 7, 14, 8, 6},   {10, 6, 9, 20, 6},   {13, 13, 26, 19, 5},
      {19, 19, 14, 5, 4},  {16, 15, 19, 13, 2}, {26, 21, 26, 12, 5}, {18, 15, 23, 20, 2}, {12, 10, 15, 20, 1},
      {26, 18, 4, 8, 3},   {8, 2, 21, 29, 2},   {19, 17, 16, 19, 1}, {10, 5, 3, 13, 3},   {16, 10, 10, 14, 1},
      {19, 18, 12, 17, 1}, {21, 21, 26, 19, 5}, {6, 5, 7, 5, 5},     {22, 20, 12, 14, 2}, {14, 13, 12, 17, 1},
      {11, 10, 16, 13, 2}, {7, 7, 23, 17, 3},   {27, 25, 13, 8, 4},  {20, 16, 19, 14, 1}, {27, 24, 10, 16, 2},
      {13, 13, 12, 6, 2},  {14, 13, 18, 23, 1}, {14, 11, 8, 1, 1},   {14, 12, 23, 9, 2},  {6, 2, 19, 13, 2},
      {8, 6, 19, 19, 3},   {18, 17, 28, 25, 3}, {29, 25, 28, 22, 2}, {15, 15, 19, 17, 3}, {23, 19, 21, 19, 1},
      {20, 20, 20, 16, 3}, {29, 25, 4, 8, 2},   {17, 16, 6, 25, 2},  {12, 8, 21, 29, 1},  {14, 9, 15, 17, 2},
      {18, 17, 5, 3, 3},   {21, 18, 12, 10, 1}, {17, 14, 14, 14, 2}, {5, 3, 26, 6, 3},    {16, 15, 13, 14, 1},
      {28, 24, 21, 22, 3}, {13, 13, 12, 10, 1}, {22, 21, 3, 11, 3},  {27, 4, 27, 16, 4},  {12, 7, 13, 10, 1},
      {15, 15, 25, 22, 2}, {19, 18, 10, 12, 1}, {17, 17, 16, 9, 2},  {21, 21, 17, 14, 2}, {13, 12, 19, 16, 1},
      {11, 9, 11, 15, 1},  {15, 14, 26, 28, 3}, {17, 17, 22, 20, 1}, {10, 2, 26, 27, 2},  {28, 26, 12, 23, 3},
      {4, 3, 5, 14, 3},    {17, 17, 7, 4, 3},   {19, 17, 15, 15, 1}, {7, 2, 8, 5, 2},     {22, 19, 15, 14, 2},
      {15, 12, 16, 20, 1}, {13, 12, 19, 20, 1}, {17, 17, 10, 8, 2},  {26, 19, 16, 15, 4}, {9, 8, 14, 20, 2},
      {27, 27, 14, 4, 4},  {17, 15, 14, 9, 1},  {5, 5, 4, 3, 3},     {15, 9, 30, 5, 1},   {7, 7, 25, 23, 6},
      {12, 11, 24, 16, 1}, {20, 20, 29, 20, 2}, {19, 15, 18, 19, 1}, {9, 7, 11, 11, 7},   {27, 26, 26, 15, 4},
      {10, 10, 28, 27, 3}, {8, 8, 12, 6, 3},    {21, 16, 23, 22, 1}, {22, 4, 7, 25, 4},   {17, 16, 19, 15, 1},
      {28, 11, 21, 15, 3}, {15, 15, 3, 2, 2},   {16, 14, 16, 17, 3}, {10, 7, 17, 18, 3},  {12, 12, 18, 15, 1},
      {18, 16, 16, 13, 1}, {20, 19, 16, 15, 1}, {16, 11, 15, 11, 1}, {4, 2, 14, 13, 2},   {29, 27, 18, 17, 2},
      {16, 14, 18, 16, 1}, {23, 22, 29, 27, 2}, {18, 18, 13, 11, 1}, {26, 21, 23, 27, 4}, {18, 17, 22, 18, 1},
      {3, 2, 11, 21, 2},   {13, 13, 18, 9, 3},  {15, 14, 14, 5, 2},  {1, 1, 14, 1, 1},    {29, 5, 2, 9, 2},
      {12, 11, 17, 17, 1}, {13, 12, 10, 25, 4}, {5, 1, 13, 25, 1},   {13, 13, 16, 12, 1}, {16, 16, 23, 12, 1},
      {27, 22, 14, 14, 2}, {29, 27, 29, 27, 2}, {23, 22, 6, 4, 4},   {22, 22, 16, 8, 3},  {14, 11, 1, 9, 1},
      {12, 10, 11, 8, 2},  {24, 7, 19, 16, 7},  {5, 2, 29, 20, 2},   {19, 19, 15, 13, 1}, {15, 8, 18, 24, 2},
      {4, 1, 24, 30, 1},   {17, 17, 30, 26, 1}, {9, 7, 8, 5, 2},     {15, 15, 20, 18, 1}, {27, 14, 5, 26, 4},
      {18, 18, 19, 15, 1}, {24, 9, 14, 12, 1},  {20, 18, 6, 10, 1},  {21, 21, 23, 21, 1}, {19, 6, 17, 6, 6},
      {10, 6, 13, 12, 3},  {30, 27, 10, 14, 1}, {9, 6, 5, 3, 3},     {26, 18, 21, 19, 2}, {23, 23, 5, 4, 4},
      {14, 11, 11, 12, 1}, {18, 16, 13, 13, 1}, {7, 3, 8, 16, 3},    {16, 16, 15, 12, 2}, {25, 24, 20, 25, 3},
      {20, 19, 14, 14, 1}, {12, 12, 29, 5, 1},  {23, 13, 17, 13, 5}, {27, 23, 27, 22, 4}, {11, 11, 4, 3, 3},
      {9, 7, 18, 15, 1},   {18, 18, 17, 14, 1}, {28, 6, 2, 17, 2},   {5, 3, 20, 22, 3},   {30, 30, 30, 2, 1},
      {16, 15, 8, 13, 1},  {15, 14, 16, 13, 1}, {28, 27, 5, 5, 3},   {13, 12, 13, 12, 1}, {7, 6, 8, 7, 6},
      {10, 10, 21, 17, 1}, {11, 3, 17, 30, 1},  {16, 9, 17, 14, 7},  {17, 9, 16, 14, 1},  {14, 13, 29, 27, 2},
      {19, 19, 5, 3, 2},   {18, 14, 16, 14, 1}, {10, 8, 23, 25, 2},  {17, 15, 17, 18, 1}, {16, 16, 22, 16, 6},
      {29, 27, 11, 11, 2}, {13, 7, 9, 11, 1},   {18, 17, 23, 19, 4}, {12, 11, 14, 17, 1}, {13, 11, 23, 18, 2},
      {27, 23, 8, 20, 4},  {18, 18, 18, 11, 4}, {8, 5, 21, 8, 5},    {23, 21, 5, 10, 1},  {16, 16, 16, 12, 1},
      {18, 14, 17, 19, 1}, {16, 16, 27, 24, 2}, {21, 15, 17, 15, 1}, {16, 15, 5, 9, 2},   {24, 1, 16, 30, 1},
      {15, 14, 14, 19, 1}, {19, 12, 12, 14, 2}, {5, 3, 5, 4, 3},     {16, 16, 11, 9, 1},  {16, 6, 9, 18, 6},
      {25, 23, 24, 14, 1}, {5, 5, 26, 17, 5},   {9, 6, 16, 18, 1},   {29, 9, 25, 24, 2},  {25, 24, 22, 30, 1},
      {22, 20, 2, 5, 2},   {27, 25, 1, 11, 1},  {15, 14, 12, 10, 1}, {17, 16, 6, 8, 1},   {28, 23, 8, 7, 3},
      {24, 23, 24, 22, 7}, {7, 5, 18, 20, 3},   {22, 20, 15, 20, 1}, {30, 28, 21, 20, 1}, {3, 2, 18, 18, 2},
      {6, 5, 14, 15, 1},   {15, 15, 18, 16, 1}, {7, 5, 11, 2, 1},    {17, 13, 17, 15, 3}, {12, 7, 15, 15, 5},
      {16, 15, 12, 18, 1}, {14, 14, 26, 25, 5}, {11, 8, 17, 18, 1},  {23, 15, 13, 21, 7}, {10, 10, 9, 2, 2},
      {17, 12, 13, 19, 1}, {20, 19, 25, 22, 1}, {9, 8, 26, 21, 1},   {19, 19, 22, 18, 1}, {8, 3, 15, 12, 1},
      {26, 16, 13, 19, 5}, {24, 21, 12, 13, 1}, {12, 12, 14, 9, 1},  {3, 1, 7, 1, 1},     {16, 15, 9, 3, 3},
      {23, 23, 20, 8, 7},  {24, 22, 16, 15, 1}, {20, 20, 19, 14, 1}, {30, 29, 27, 22, 1}, {27, 4, 17, 16, 4},
      {8, 5, 13, 13, 5},   {19, 10, 8, 16, 3},  {30, 30, 11, 4, 1},  {14, 14, 21, 20, 1}, {14, 13, 11, 13, 1},
      {30, 28, 2, 5, 1},   {17, 12, 29, 24, 2}, {15, 6, 25, 30, 1},  {4, 1, 1, 1, 1},     {12, 5, 16, 20, 5},
      {16, 14, 20, 15, 1}, {6, 6, 17, 9, 3},    {20, 12, 17, 20, 4}, {15, 12, 15, 4, 4},  {28, 22, 20, 21, 3},
      {14, 9, 18, 18, 5},  {26, 23, 1, 5, 1},   {21, 11, 24, 10, 7}, {15, 14, 19, 12, 1}, {27, 11, 29, 16, 1},
      {23, 22, 19, 29, 1}, {2, 2, 30, 29, 1},   {14, 6, 16, 5, 3},   {17, 14, 13, 16, 1}, {19, 15, 14, 16, 1},
      {20, 13, 25, 15, 6}, {19, 11, 18, 12, 5}, {30, 30, 30, 13, 1}, {3, 1, 14, 9, 1},    {20, 1, 17, 18, 1},
      {16, 12, 20, 19, 1}};
    thresholds_ = {
      21.65, 5.65,   4.95,   2.45,  2.25,   0.85,  3.35,   1.75,   4.55,  -1.55, 4.55,  -5.05, 3.15,  4.85,  9.95,
      1.35,  -2.05,  -0.15,  1.55,  3.35,   0.25,  0.35,   2.45,   2.75,  -1.65, -0.05, -0.75, 0.85,  2.95,  -1.65,
      -0.05, -0.25,  -3.85,  -0.05, 3.35,   0.05,  -3.55,  2.65,   1.95,  6.35,  0.85,  2.65,  12.45, 0.05,  3.35,
      1.75,  -1.05,  -1.05,  28.25, 0.35,   -0.15, 2.05,   2.55,   0.85,  1.35,  1.15,  1.25,  1.35,  1.85,  3.95,
      0.75,  1.65,   -3.15,  -6.35, 2.05,   -5.15, 1.75,   -0.65,  -0.65, 1.05,  -0.85, 0.85,  -0.35, 9.05,  0.75,
      -1.75, 0.75,   16.05,  0.35,  0.75,   0.05,  0.05,   3.75,   14.15, -8.95, 67.25, -0.45, 1.65,  -1.95, 1.15,
      1.85,  3.95,   -1.75,  0.45,  -1.55,  1.05,  -0.25,  -1.05,  3.05,  -1.05, 1.95,  -0.05, 0.85,  3.05,  34.85,
      -0.15, 4.35,   -10.65, 2.35,  -1.35,  0.05,  1.05,   1.05,   -0.15, 0.45,  -0.55, 10.45, 1.35,  -0.95, 0.45,
      -0.85, 1.45,   -1.85,  1.65,  2.75,   1.05,  81.45,  3.35,   0.85,  2.65,  9.35,  1.15,  1.35,  -1.55, 0.85,
      20.65, 2.05,   12.85,  7.95,  2.25,   0.05,  0.85,   8.75,   -8.25, -0.35, 1.65,  -3.95, 92.55, 0.55,  0.35,
      -0.75, -12.25, 0.55,   1.05,  0.95,   1.15,  -43.25, 3.05,   4.35,  7.15,  0.15,  57.95, 4.35,  0.75,  0.05,
      0.05,  5.45,   0.55,   0.95,  20.55,  -4.45, 0.75,   4.55,   -0.15, 8.65,  42.65, -0.45, -1.25, -1.75, 11.25,
      -8.15, 2.85,   -2.85,  -5.05, 44.65,  1.45,  -0.75,  11.85,  2.05,  1.25,  4.45,  -1.35, 5.95,  1.35,  -2.55,
      5.05,  -2.85,  7.35,   -1.35, -0.45,  0.45,  -11.85, -39.65, 1.65,  -0.05, 3.65,  -0.35, 0.05,  1.85,  -0.45,
      -1.75, 3.95,   5.25,   -1.05, -11.95, 37.05, -1.15,  1.25,   0.75,  -6.05, -1.55, -1.65, 0.85,  0.35,  101.55,
      -5.05, 3.65,   -2.35,  -0.35, -1.65,  0.65,  6.35,   2.85,   5.25,  24.05, 38.15, -1.05, 3.05,  0.35,  -16.05,
      -1.25, 0.25,   1.95,   -0.85, 107.65, -1.55, -0.25,  26.95,  35.95, -4.85, 1.55,  10.85, -7.15, -4.25, -25.15,
      2.75};
  }
}

void BAD::compute(cv::InputArray _image,
                  std::vector<cv::KeyPoint> &keypoints,
                  cv::OutputArray &_descriptors) {
  cv::Mat image = _image.getMat();

  if (image.empty())
    return;

  if (keypoints.empty()) {
    // clean output buffer (it may be reused with "allocated" data)
    _descriptors.release();
    return;
  }

  assert(image.type() == CV_8UC1);
  cv::Mat integral_img;

  // compute the integral image
  cv::integral(image, integral_img);

  // Create the output array of descriptors
  _descriptors.create(static_cast<int>(keypoints.size()), descriptorSize(), descriptorType());

  // descriptor storage
  cv::Mat descriptors = _descriptors.getMat();
  assert(descriptors.type() == CV_8UC1);

  computeBAD(integral_img, keypoints, descriptors);
}

void BAD::computeBAD(const cv::Mat &integral_img,
                     const std::vector<cv::KeyPoint> &keypoints,
                     cv::Mat &descriptors) {
  assert(!integral_img.empty());
  assert(descriptors.rows == keypoints.size());

  const int *integral_ptr = integral_img.ptr<int>();
  cv::Size frame_size(integral_img.cols - 1, integral_img.rows - 1);

  /////////////////// Parallel Loop to process descriptors ////////////////////

#ifndef UPM_BAD_PARALLEL
  const cv::Range range(0, keypoints.size());
#else
  cv::parallel_for_(cv::Range(0, static_cast<int>(keypoints.size())), [&](const cv::Range &range){  // NOLINT
#endif
  // Get a pointer to the first element in the range
  // Get a pointer to the first element in the range
  BoxPairParams *box_pair;
  float response_fun;
  int area_response_fun, kpIdx;
  size_t box_pair_idx;
  int box1x1, box1y1, box1x2, box1y2, box2x1, box2y1, box2x2, box2y2, bit_idx, side;
  uchar byte = 0;
  std::vector<BoxPairParams> img_boxes(box_params_.size());
  uchar *d = &descriptors.at<uchar>(range.start, 0);

  for (kpIdx = range.start; kpIdx < range.end; kpIdx++) {
    // Rectify the weak learners coordinates using the keypoint information
    // Rectify the weak learners coordinates using the keypoint information
    rectifyBoxes(box_params_, img_boxes, keypoints[kpIdx], scale_factor_, patch_size_);
    if (isKeypointInTheBorder(keypoints[kpIdx], frame_size, patch_size_, scale_factor_)) {
      // Code to process the keypoints in the image margins
      for (box_pair_idx = 0; box_pair_idx < box_params_.size(); box_pair_idx++) {
        bit_idx = 7 - static_cast<int>(box_pair_idx % 8);
        response_fun = computeBadResponse(img_boxes[box_pair_idx], integral_img);
        // Set the bit to 1 if the response function is less or equal to the threshod
        byte |= (response_fun <= thresholds_[box_pair_idx]) << bit_idx;
        // If we filled the byte, save it
        if (bit_idx == 0) {
          *d = byte;
          byte = 0;
          d++;
        }
      }
    } else {
      // Code to process the keypoints in the image center
      box_pair = img_boxes.data();
      for (box_pair_idx = 0; box_pair_idx < box_params_.size(); box_pair_idx++) {
        bit_idx = 7 - static_cast<int>(box_pair_idx % 8);

        // For the first box, we calculate its margin coordinates
        box1x1 = box_pair->x1 - box_pair->boxRadius;
        box1y1 = (box_pair->y1 - box_pair->boxRadius) * integral_img.cols;
        box1x2 = box_pair->x1 + box_pair->boxRadius + 1;
        box1y2 = (box_pair->y1 + box_pair->boxRadius + 1) * integral_img.cols;
        // For the second box, we calculate its margin coordinates
        box2x1 = box_pair->x2 - box_pair->boxRadius;
        box2y1 = (box_pair->y2 - box_pair->boxRadius) * integral_img.cols;
        box2x2 = box_pair->x2 + box_pair->boxRadius + 1;
        box2y2 = (box_pair->y2 + box_pair->boxRadius + 1) * integral_img.cols;
        side = 1 + (box_pair->boxRadius << 1);

        // Get the difference between the average level of the two boxes
        area_response_fun = (integral_ptr[box1y1 + box1x1]  // A of Box1
            + integral_ptr[box1y2 + box1x2]               // D of Box1
            - integral_ptr[box1y1 + box1x2]               // B of Box1
            - integral_ptr[box1y2 + box1x1]               // C of Box1
            - integral_ptr[box2y1 + box2x1]               // A of Box2
            - integral_ptr[box2y2 + box2x2]               // D of Box2
            + integral_ptr[box2y1 + box2x2]               // B of Box2
            + integral_ptr[box2y2 + box2x1]);             // C of Box2

        // Set the bit to 1 if the response function is less or equal to the threshod
        byte |= (area_response_fun <= (thresholds_[box_pair_idx] * (side * side))) << bit_idx;
        box_pair++;
        // If we filled the byte, save it
        if (bit_idx == 0) {
          *d = byte;
          byte = 0;
          d++;
        }
      }  // End of for each dimension
    }  // End of else (of pixels in the image center)
  }  // End of for each keypoint
#ifdef UPM_BAD_PARALLEL
  });
#endif
  }  // namespace upm  ## NOLINT
}
